package com.bc.bcapi.service;

import com.bc.bcapi.dao.T_Mng_email_confMapper;
import com.bc.bccore.redis.RedisService;
import com.bc.bccore.util.MailSender;
import com.bc.bccore.webconfig.WebConfig;
import com.bc.bcmodel.domain.T_Mng_email_confModel;
import com.bc.bcmodel.enums.EmailTemplateEnum;
import com.bc.bcmodel.req.MngEmailSysReq;
import com.bc.bcmodel.req.SendMailModelReq;
import com.bc.bcmodel.resp.MngSendEmailResp;
import com.bc.commoncore.util.*;
import com.bc.commonentity.common.JsonResult;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.io.Resources;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.mail.*;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.util.*;
import java.math.BigInteger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.bc.bcapi.dao.T_Mng_email_sysMapper;
import com.bc.bcmodel.domain.T_Mng_email_sysModel;

/**
 * @Name T_Mng_email_sysService * @Description  * @Author generation * @Date 2018/9/12 15:29:31 * @Version 1.0
 **/
@Service
public class T_Mng_email_sysService {
    @Resource
    T_Mng_email_sysMapper t_Mng_email_sysMapper;
    @Resource
    T_Mng_email_confMapper t_mng_email_confMapper;
    @Resource
    RedisService redisService;
    private static HashMap<String, String> hashEmailContent = null;
    static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);

    /**
     * 保存单条数据     *      * @return
     */
    public int insert(T_Mng_email_sysModel req) {
        return t_Mng_email_sysMapper.insert(req);
    }

    /**
     * 批量增加数据     *      * @return
     */
    public int insertBatch(List<T_Mng_email_sysModel> req) {
        return t_Mng_email_sysMapper.insertBatch(req);
    }

    /**
     * 根据对象属性查找满足条件的第一条数据     *      * @return
     */
    public T_Mng_email_sysModel findByNamedParam(T_Mng_email_sysModel req) {
        return t_Mng_email_sysMapper.findByNamedParam(req);
    }

    /**
     * 根据对象查询所有数据     *      * @return
     */
    public List<T_Mng_email_sysModel> getAllList(T_Mng_email_sysModel req) {
        return t_Mng_email_sysMapper.findByNamedParamList(req);
    }

    /**
     * 根据对象查询所有分页数据     *      * @return
     */
    public PageInfo<T_Mng_email_sysModel> getList(MngEmailSysReq req) {
        PageHelper.startPage(req.getPage_index(), req.getPage_size());
        List<T_Mng_email_sysModel> list = t_Mng_email_sysMapper.getList(req);
        return new PageInfo<T_Mng_email_sysModel>(list);
    }

    /**
     * 更新指定对象     *      * @return
     */
    public int update(T_Mng_email_sysModel req) {
        return t_Mng_email_sysMapper.update(req);
    }

    /**
     * 删除指定数据     *      * @return
     */
    public int delete(BigInteger id) {
        return t_Mng_email_sysMapper.delete(id);
    }

    /**
     * 根据条件统计数据量     *      * @return
     */
    public long count(T_Mng_email_sysModel req) {
        return t_Mng_email_sysMapper.count(req);
    }

    /**
     * param
     * to_email:收件人
     * edesc:格式例子：[{"key":"yanzhengma","value":"12345"},{"key":"zhanghao","value":"dhc"}]
     * edesc 计算方式
     * List<MngSendEmailResp> list = new ArrayList<MngSendEmailResp>();
     * MngSendEmailResp one = new MngSendEmailResp();
     * one.setKey("yanzhengma");
     * one.setValue("woshiyanzhengma");
     * MngSendEmailResp two = new MngSendEmailResp();
     * two.setKey("zhanghao");
     * two.setValue("douhaichao");
     * list.add(one);
     * list.add(two);
     * String edesc = JsonUtil.obj2string(list);
     */
    public void sendSystemEmailSync(EmailTemplateEnum emailTemplateEnum, String to_email,
                                    String edesc, HttpServletRequest request) {

        fixedThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    String language = CookieUtils.getCookie(request, "local");
                    if (StringUtils.isEmpty(language)) {
                        language = "zh";
                    }
                    String title = getEmailTitle(emailTemplateEnum, language);
                    T_Mng_email_sysModel toModel = sendSystemEmail(emailTemplateEnum.toString(), title, to_email, edesc);
//                    sendSysEmail();
                    sendCurrentSysEmail(to_email, toModel);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private String getEmailTitle(EmailTemplateEnum emailTemplateEnum, String language) {
        String title = "";
        if (language.equals("zh")) {
            title = emailTemplateEnum.zh();
        } else {
            title = emailTemplateEnum.en();
        }
        return title;
    }

    private T_Mng_email_sysModel sendSystemEmail(String type, String title, String to_email, String edesc) {
        T_Mng_email_sysModel t_mng_email_sysModel = new T_Mng_email_sysModel();
        t_mng_email_sysModel.setType(title);
        t_mng_email_sysModel.setTo_email(to_email);
        t_mng_email_sysModel.setEdesc(edesc);
        t_mng_email_sysModel.setTitle(title);
        return t_mng_email_sysModel;
//        t_Mng_email_sysMapper.insert(t_mng_email_sysModel);
    }

    private List<T_Mng_email_confModel> getListConf() {
        String key = "email:send:list";
        String emailCoonfStr = redisService.get(key);
//        redisService.remove(key, true);
        if (StringUtils.isEmpty(emailCoonfStr)) {
            List<T_Mng_email_confModel> listConf = t_mng_email_confMapper.getAll();
            redisService.set(key, JsonUtil.obj2string(listConf), 5, TimeUnit.MINUTES);
            return listConf;
        }
        return JsonUtil.str2list(emailCoonfStr, T_Mng_email_confModel.class);
    }

    private void initSendEmailContent() {
        if (hashEmailContent != null) {
            return;
        }
        hashEmailContent = new HashMap<String, String>();
        EmailTemplateEnum[] listEmail = EmailTemplateEnum.values();
        for (EmailTemplateEnum item :
                listEmail) {
            getContentData(item.en());
            getContentData(item.zh());

        }
    }

    private static void getContentData(String key) {
        try {
            /**
             * 英文开始
             * */
            StringBuilder sb_en = new StringBuilder();
            String html_en = "";
            BufferedInputStream bufferedInputStream =
                    (BufferedInputStream)
                            Resources.getResource("templatemail/" + key + ".html").getContent();
            byte[] bs_en = new byte[1024];

            while (bufferedInputStream.read(bs_en) != -1) {
                sb_en.append(new String(bs_en));
            }
            html_en = sb_en.toString();
            String html = new String(html_en.getBytes(), "UTF-8");
            html = html.substring(0, html.indexOf("</html>") + 7);
            hashEmailContent.put(key, html);
        } catch (IOException e) {
        }
    }

    public JsonResult sendCurrentSysEmail(String toEmail, T_Mng_email_sysModel toModel) {
        initSendEmailContent();
        JsonResult js = new JsonResult();
        //获取出from邮件->取出昨天-今天发送次数，给发送次数多的降权
        List<T_Mng_email_confModel> listSendConfig = getListConf();
        //获取to邮件->状态为未发送的
        T_Mng_email_confModel from_email = null;
        String to = toEmail;
        String todomain = to.substring(to.indexOf("@") + 1);
        List<T_Mng_email_confModel> listSendFilter = listSendConfig.stream().filter(
                t -> t.getSmtp().contains(todomain)).collect(Collectors.toList());
        if (listSendFilter == null || listSendFilter.size() <= 0) {
            from_email = listSendConfig.get(0);
        } else {
            from_email = listSendFilter.get(0);
        }
        //开发发送邮件
//        SendEmail(from_email, toModel);
        SendEmailSSL(from_email, toModel);
//        }
        return js;
    }

    /**
     * 系统邮件发送--集合发送
     */
    public JsonResult sendSysEmail() {

        JsonResult js = new JsonResult();
        //获取出from邮件->取出昨天-今天发送次数，给发送次数多的降权
        List<T_Mng_email_confModel> listSendConfig = getListConf();
        //获取to邮件->状态为未发送的
        T_Mng_email_sysModel t_mng_email_sysModel = new T_Mng_email_sysModel();
        t_mng_email_sysModel.setStatus(0);
        List<T_Mng_email_sysModel> listSend = t_Mng_email_sysMapper.findByNamedParamList(t_mng_email_sysModel);
        for (T_Mng_email_sysModel item :
                listSend) {
            T_Mng_email_confModel from_email = null;
            String to = item.getTo_email();
            String todomain = to.substring(to.indexOf("@") + 1);
            List<T_Mng_email_confModel> listSendFilter = listSendConfig.stream().filter(
                    t -> t.getSmtp().contains(todomain)).collect(Collectors.toList());
            if (listSendFilter == null || listSendFilter.size() <= 0) {
                from_email = listSendConfig.get(0);
            } else {
                from_email = listSendFilter.get(0);
            }
            //开发发送邮件
//            SendEmail(from_email, item);
            SendEmailSSL(from_email, item);
        }
        return js;
    }

    private String getEmailContent(T_Mng_email_sysModel model) {
        initSendEmailContent();
        String html = "";
        try {
            html = hashEmailContent.get(model.getType());
            String content = model.getEdesc();
            List<MngSendEmailResp> list = JsonUtil.str2list(content, MngSendEmailResp.class);
            for (MngSendEmailResp item :
                    list) {
                html = html.replace("${" + item.getKey() + "}", item.getValue());
            }
        } catch (Exception e) {
        }
        return html;
    }

    public int Send(T_Mng_email_confModel fromModel, T_Mng_email_sysModel toModel) {
        //emailAddress  收件人邮箱
        boolean isSSL = true;
        String host = fromModel.getSmtp();// "smtp.163.com";
        int port = fromModel.getPort(); //465;
        String from = fromModel.getFrom_email(); // "********@163.com";
        // 发件人的email
        boolean isAuth = true;
        final String password = fromModel.getPwd();
        Properties props = new Properties();
        props.put("mail.smtp.ssl.enable", isSSL);
        props.put("mail.smtp.host", host);
        props.put("mail.smtp.port", port);
        props.put("mail.smtp.auth", isAuth);
        Session session = Session.getDefaultInstance(props, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(from, password);
            }
        });
        int send_status = 0;
        try {
            send_status = 1;
            String content = getEmailContent(toModel);
            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress(from));
            message.addRecipient(Message.RecipientType.TO, new InternetAddress(toModel.getTo_email()));
            message.setSubject(toModel.getTitle());
            message.setContent(content, "text/html;charset=utf-8");
            Transport.send(message);
        } catch (
                Exception e) {
            System.out.println(e.getMessage());
            send_status = 2;
        }
        return send_status;
    }

    private void SendEmailSSL(T_Mng_email_confModel fromModel, T_Mng_email_sysModel toModel) {
        int send_status = Send(fromModel, toModel);
        String tryUrl = WebConfig.getTrySendEmailUrl();
        //临时全部认为是失败，主要为了测试国内的发送
//        send_status = 2;
        if (send_status != 1 && !StringUtils.isEmpty(tryUrl)) {
            //调用远程发送邮件
            SendMailModelReq resp = new SendMailModelReq();
            resp.setFrom(fromModel);
            resp.setTo(toModel);

            String param = JsonUtil.obj2string(resp);
            String resultData = HttpUtil.sendJsonPost(tryUrl, param);
            send_status = ParseHelper.ToInt(resultData);
        }
        toModel.setStatus(send_status);
        t_Mng_email_sysMapper.insert(toModel);
        if (send_status != 1) {
            //修改错误率
            t_mng_email_confMapper.updateErrorCount(fromModel.getId());
        }
    }

    private void SendEmail(T_Mng_email_confModel fromModel, T_Mng_email_sysModel toModel) {
//获取邮件发送内容
        String content = getEmailContent(toModel);
        MailSender.Builder b = new MailSender.Builder(content, toModel.getTo_email());
        b.Host(fromModel.getSmtp());
        b.Subject(toModel.getTitle());
        b.FromAddress(fromModel.getFrom_email());
        b.FromCount(fromModel.getFrom_email());
        b.FromPassword(fromModel.getPwd());
        int send_status = 0;
        try {
            b.send();
            send_status = 1;
        } catch (Exception e) {
            System.out.print(e.getMessage());
            send_status = 2;
        } finally {
            toModel.setStatus(send_status);
            t_Mng_email_sysMapper.insert(toModel);
            if (send_status == 1) {
                //修改错误率
                t_mng_email_confMapper.updateErrorCount(fromModel.getId());
            }
        }

    }
}